package com.ht.api.db.task;

import java.util.concurrent.TimeUnit;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import lombok.Data;

/**
 * 任务执行计划
 * @author asq
 * @createTime 2024年12月10日 13:42:16
 */
@Data
public class Plan {
	private Integer initialInterval; // 初始间隔(秒)
	private Integer maxInterval; // 最大间隔(秒)
	private Double intervalMultiplier; // 间隔增长倍数
	private Long maxTimes; // 最大执行时间
	private Integer maxNum; // 最大执行次数
	private Integer startTime; // 开始执行时间(秒级时间戳)
	private String cronExpression; // 定时任务表达式
	
	private Plan() {
	}
	
	public static Plan create() {
		return new Plan();
	}
	
	/**
	 * 设置初始间隔（秒）<br>
	 * 不设置则只执行一次
	 * @param second 秒
	 * @return
	 */
	public Plan setMin(int second) {
		this.initialInterval = second;
		return this;
	}
	
	/**
	 * 设置最大间隔（秒）<br>
	 * 不设置则一直按初始间隔执行
	 * @param second 秒
	 * @return
	 */
	public Plan setMax(int second) {
		this.maxInterval = second;
		return this;
	}
	
	/**
	 * 设置间隔增长倍数<br>
	 * 不设置则一直按初始间隔执行
	 * @param rate
	 * @return
	 */
	public Plan setRate(double rate) {
		this.intervalMultiplier = rate;
		return this;
	}
	
	/**
	 * 设置最大执行时间<br>
	 * 最大执行次数优先于最大执行时间<br>
	 * 都未设置则循环执行
	 * @param time
	 * @param timeUnit
	 * @return
	 */
	public Plan setTimes(int time, TimeUnit timeUnit) {
		this.maxTimes = timeUnit.toSeconds(time);
		return this;
	}
	
	/**
	 * 设置最大执行次数<br>
	 * 最大执行次数优先于最大执行时间<br>
	 * 都未设置则循环执行
	 * @param maxNum
	 * @return
	 */
	public Plan setNum(int maxNum) {
		this.maxNum = maxNum;
		return this;
	}
	
	/**
	 * 设置开始执行时间<br>
	 * 不设置则立即执行
	 * @param startTime 秒级时间戳
	 * @return
	 */
	public Plan at(int startTime) {
		this.startTime = startTime;
		return this;
	}
	
	/**
	 * 设置开始执行时间<br>
	 * 不设置则立即执行
	 * @param startTimeOrCron 时间字符串或cron表达式，时间格式：yyyy-MM-dd HH:mm:ss，cron表达式：0/5 * * * * ? *
	 * @return
	 */
	public Plan at(String startTimeOrCron) {
		try {
			DateTime dateTime = DateUtil.parse(startTimeOrCron);
			this.startTime = (int) (dateTime.getTime() / 1000);
		} catch (Exception e) {
			this.cronExpression = startTimeOrCron;
		}
		return this;
	}

	/**
	 * 设置执行计划
	 * @param task
	 */
	public void setPlan(TaskInfo task) {
		if (this.initialInterval != null) {
			task.setInitialInterval(this.initialInterval);
			task.setExecuteOnce(false);
		} else {
			task.setExecuteOnce(true);
		}
		if (this.maxInterval != null) {
			task.setMaxInterval(this.maxInterval);
		} else {
			task.setMaxInterval(Integer.MAX_VALUE);
		}
		if (this.intervalMultiplier != null) {
			task.setIntervalMultiplier(this.intervalMultiplier);
		}
		if (this.maxTimes != null) {
			task.setMaxTimes(this.maxTimes);
		}
		if (this.maxNum != null) {
			task.setMaxNum(this.maxNum);
		}
		if (this.startTime != null) {
			String startTimeStr = DateUtil.date(this.startTime * 1000L).toString("yyyy-MM-dd HH:mm:ss");
			task.setStartTime(startTimeStr);
		} else {
			task.setStartTime(DateUtil.now());
		}
		if (this.cronExpression != null) {
			task.setCronExpression(cronExpression);
		}
	}
}
